﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using Jobs;
using Microsoft.WindowsAPICodePack.Taskbar;
using Monitor.Core.Utilities;
using SteamTools;
using Yak;

namespace Sagenhaft
{
    public partial class MainWindow : Form
    {
        Int64 FreierPlatz;
        Int64 BenötigterPlatz;

        Int64 Spielgröße;

        DriveInfo ZielDrive;

        private enum Aktionen { Redirect, Backdirect, Moveaway, Moveback };

        private Aktionen Aktion;

        private List<Schiebejob> MoveJobs = new List<Schiebejob>();
        private List<Umleitjob> RedirJobs = new List<Umleitjob>();

        private String AuxDirectory;

        private String ProjectName = Env.ProjectName;

        private StringCollection Quellordnerliste = new StringCollection();

        public MainWindow()
        {
            InitializeComponent();
        }

        private void wizardControl1_SelectedPageChanged(object sender, EventArgs e)
        {

        }

        private void wizardControl1_Cancelling(object sender, CancelEventArgs e)
        {
            Application.Exit();
        }

        private void Aktionwahl_Commit(object sender, AeroWizard.WizardPageConfirmEventArgs e)
        {
            if (radioButton1.Checked)
            {
                Wizard.Title = radioButton1.Text;
                Aktion = Aktionen.Moveaway;
            }
            else if (radioButton2.Checked)
            {
                Wizard.Title = radioButton2.Text;
                Aktion = Aktionen.Moveback;
            }
            else if (radioButton3.Checked)
            {
                Wizard.Title = radioButton3.Text;
                Aktion = Aktionen.Redirect;
            }
            else if (radioButton4.Checked)
            {
                Wizard.Title = radioButton4.Text;
                Aktion = Aktionen.Backdirect;
            }
            //Hilfsordnerwahl überspringen, wenn Rückleiten
            if (Aktion != Aktionen.Backdirect)
                Aktionwahl.NextPage = Ordnerwahl;
            else //Backdirect
                Aktionwahl.NextPage = Spielwahl;
        }

        private void Ordnerwahl_Initialize(object sender, AeroWizard.WizardPageInitEventArgs e)
        {
            OrdnerwahlFehler.Text = null;
            if (Aktion != Aktionen.Backdirect)
            {
                textBox1.Enabled = true;
                button1.Enabled = true;
                textBox1.Text = Properties.Settings.Default.AuxDirectory;
                if ((!Directory.Exists(textBox1.Text)) || (FSUtils.GetRoot(SteamFolders.Common) == FSUtils.GetRoot(textBox1.Text)) || ((Aktion == Aktionen.Redirect) && ((new DriveInfo(Path.GetPathRoot(textBox1.Text)).DriveFormat != "NTFS" || (new DriveInfo(Path.GetPathRoot(textBox1.Text)).DriveType != DriveType.Fixed))))||(!FSUtils.CanIWrite(textBox1.Text)))
                {
                    Ordnerwahl.AllowNext = false;
                    BrowseFolder();
                }
                else
                    Ordnerwahl.AllowNext = true;
            }
            else
            {
                textBox1.Enabled = false;
                button1.Enabled = false;
                Ordnerwahl.AllowNext = true;
            }
            
        }

        private void BrowseFolder()
        {
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                textBox1.Text = folderBrowserDialog1.SelectedPath;
                if (FSUtils.GetRoot(SteamFolders.Common) == FSUtils.GetRoot(textBox1.Text))
                {
                    Ordnerwahl.AllowNext=false;
                    OrdnerwahlFehler.Text="This folder is on the same drive as Steam";
                }
                else if ((Aktion == Aktionen.Redirect) && (new DriveInfo(Path.GetPathRoot(textBox1.Text)).DriveType != DriveType.Fixed))
                {
                    Ordnerwahl.AllowNext=false;
                    OrdnerwahlFehler.Text="Folder must reside on a fixed drive";
                }
                else if ((Aktion == Aktionen.Redirect) && (new DriveInfo(Path.GetPathRoot(textBox1.Text)).DriveFormat != "NTFS"))
                {
                    Ordnerwahl.AllowNext = false;
                    OrdnerwahlFehler.Text = "Folder must reside on a NTFS drive";
                }
                else if (!FSUtils.CanIWrite(textBox1.Text))
                {
                    OrdnerwahlFehler.Text = "No write privileges for that folder";
                    Ordnerwahl.AllowNext = false;
                }
                else
                {
                    Properties.Settings.Default.AuxDirectory = textBox1.Text;
                    Properties.Settings.Default.Save();
                    Ordnerwahl.AllowNext = true;
                    OrdnerwahlFehler.Text = null;
                }
            }
        }

        private void Saga_Load(object sender, EventArgs e)
        {
            label2.Text = null;
            Wizard.Title = ProjectName;
            this.Text = ProjectName;
        }

        private void linkLabel1_Click(object sender, EventArgs e)
        {
            Process.Start("mailto:ReBootOnSteam@live.de?subject="+ProjectName);
        }

        private void Ordnerwahl_Commit(object sender, AeroWizard.WizardPageConfirmEventArgs e)
        {
                AuxDirectory = textBox1.Text;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            BrowseFolder();
        }

        private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start("http://sagenhaft.codeplex.com");
        }

        private void Spielwahl_Initialize(object sender, AeroWizard.WizardPageInitEventArgs e)
        {
            SpielwahlFehler.Text = null;
            if (Aktion == Aktionen.Moveaway || Aktion == Aktionen.Redirect)
            {
                ZielDrive = new DriveInfo(Path.GetPathRoot(AuxDirectory));
            }
            else if (Aktion == Aktionen.Moveback || Aktion == Aktionen.Backdirect)
            {
                ZielDrive = new DriveInfo(Path.GetPathRoot(SteamFolders.Common));
            }
            FreierPlatz = ZielDrive.AvailableFreeSpace;
            BenötigterPlatz = 0;
            checkedListBox1.Items.Clear();
            Spielwahl.AllowNext = false;
            if (Aktion == Aktionen.Moveaway)
            {
                foreach (String foo in SteamFolders.CommonGameFolders)
                    if (!NativeMethods.Exists(foo))
                        checkedListBox1.Items.Add(Path.GetFileNameWithoutExtension(foo));
            }
            else if (Aktion == Aktionen.Moveback)
            {
                foreach (String foo in Directory.GetDirectories(AuxDirectory))
                    if (!NativeMethods.Exists(foo))
                        checkedListBox1.Items.Add(Path.GetFileNameWithoutExtension(foo));
            }
            else if (Aktion == Aktionen.Redirect)
            {
                foreach (String foo in SteamFolders.CommonGameFolders)
                    if (!NativeMethods.Exists(foo))
                        checkedListBox1.Items.Add(Path.GetFileNameWithoutExtension(foo));
            }
            else if (Aktion == Aktionen.Backdirect)
            {
                foreach (String foo in SteamFolders.CommonGameFolders)
                    if (NativeMethods.Exists(foo))
                        checkedListBox1.Items.Add(Path.GetFileNameWithoutExtension(foo));
            }
        }

        private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            if (Aktion == Aktionen.Moveaway||Aktion==Aktionen.Redirect)
                Spielgröße = FSUtils.DirectorySize(new DirectoryInfo(Path.Combine(SteamFolders.Common, checkedListBox1.Items[e.Index].ToString())));
            else if (Aktion==Aktionen.Moveback)
                Spielgröße = FSUtils.DirectorySize(new DirectoryInfo(Path.Combine(AuxDirectory, checkedListBox1.Items[e.Index].ToString())));
            else //(Aktion==Aktionen.Backdirect)
                Spielgröße = FSUtils.DirectorySize(new DirectoryInfo(NativeMethods.GetTarget(Path.Combine(SteamFolders.Common,checkedListBox1.Items[e.Index].ToString()))));
            if (e.NewValue == CheckState.Checked && e.CurrentValue == CheckState.Unchecked)
            {
                BenötigterPlatz += Spielgröße;
                FreierPlatz -= Spielgröße;
            }
            else if (e.NewValue == CheckState.Unchecked && e.CurrentValue == CheckState.Checked)
            {
                BenötigterPlatz -= Spielgröße;
                FreierPlatz += Spielgröße;
            }
            if (BenötigterPlatz == 0)
            {
                Spielwahl.AllowNext = false;
                SpielwahlFehler.Text = null;
            }
            else if (BenötigterPlatz < FreierPlatz)
            {
                Spielwahl.AllowNext = true;
                SpielwahlFehler.Text = null;
            }
            else
            {
                Spielwahl.AllowNext = false;
                SpielwahlFehler.Text = "Not enough space on " + ZielDrive.ToString();
            }
        }

        private void Spielwahl_Commit(object sender, AeroWizard.WizardPageConfirmEventArgs e)
        {
            if (Aktion == Aktionen.Moveaway)
            {
                MoveJobs.Clear();
                foreach (Object Item in checkedListBox1.CheckedItems)
                {
                    MoveJobs.Add(new Schiebejob(Path.Combine(SteamFolders.Common,Item.ToString()),Path.Combine(AuxDirectory,Item.ToString())));
                }
            }
            else if (Aktion==Aktionen.Moveback)
            {
                MoveJobs.Clear();
                foreach (Object Item in checkedListBox1.CheckedItems)
                {
                    MoveJobs.Add(new Schiebejob(Path.Combine(AuxDirectory, Item.ToString()), Path.Combine(SteamFolders.Common, Item.ToString())));
                }
            }
            else if (Aktion==Aktionen.Redirect)
            {
                RedirJobs.Clear();
                foreach (Object Item in checkedListBox1.CheckedItems)
                {
                    RedirJobs.Add(new Umleitjob(Path.Combine(SteamFolders.Common, Item.ToString()), Path.Combine(AuxDirectory, Item.ToString())));
                }
            }
            else if (Aktion==Aktionen.Backdirect)
            {
                MoveJobs.Clear();
                foreach (Object Item in checkedListBox1.CheckedItems)
                {
                    MoveJobs.Add(new Schiebejob(NativeMethods.GetTarget(Path.Combine(SteamFolders.Common, Item.ToString())), Path.Combine(SteamFolders.Common, Item.ToString())));
                }
            }
        }

        private void Fertig_Initialize(object sender, AeroWizard.WizardPageInitEventArgs e)
        {
            textBox2.ResetText();
            Fertig.Text = "Processing";
            Fertig.AllowNext = false;
            backgroundWorker1.RunWorkerAsync();
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            int i = 0;
            if (Aktion != Aktionen.Redirect)
                foreach (Schiebejob Job in MoveJobs)
                {
                    Job.Execute();
                    i++;
                    backgroundWorker1.ReportProgress(i, Path.GetFileNameWithoutExtension(Job.Quellordner)+" processed");
                }
            else //Redirect
            {
                foreach (Umleitjob Job in RedirJobs)
                {
                    Job.Execute();
                    i++;
                    backgroundWorker1.ReportProgress(i, Path.GetFileNameWithoutExtension(Job.Quellordner)+" processed");
                }
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            textBox2.Text += e.UserState.ToString()+Environment.NewLine;
            if (TaskbarManager.IsPlatformSupported)
            {
                TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.Normal);
                if (Aktion != Aktionen.Redirect)
                   TaskbarManager.Instance.SetProgressValue(e.ProgressPercentage,MoveJobs.Count);
                else //Redirect
                    TaskbarManager.Instance.SetProgressValue(e.ProgressPercentage, RedirJobs.Count);
            }
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (TaskbarManager.IsPlatformSupported)
            {
                TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.NoProgress);
            }
            Fertig.Text = "Process completed";
            Fertig.AllowNext = true;
        }

        private void wizardControl1_Finished(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {
            textBox2.SelectionStart = textBox2.Text.Length;
            textBox2.ScrollToCaret();
        }

        private void Aktionwahl_Initialize(object sender, AeroWizard.WizardPageInitEventArgs e)
        {
            Wizard.Title = ProjectName;
        }
    }
}
